#include <iostream>
#include <cassert>
#include <ctime>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>
#include "BlockQueue.hpp"
#include "Task.hpp"

int myAdd(int x, int y)
{
    return x + y;
}

void *consume(void *args)
{
    BlockQueue<Task> *pbq = (BlockQueue<Task>*)args;

    Task task;
    while(true)
    {
        // 间隔1秒读取数据
        pbq->pop(&task);
        printf("%d + %d = %d\n", task._x, task._y, task());
        sleep(1);
    }
}

void *product(void *args)
{
    BlockQueue<Task> *pbq = (BlockQueue<Task>*)args;

    while(true)
    {
        int x = rand() % 15;
        usleep(1000);
        int y = rand() % 15;

        printf("%d + %d = ?\n", x, y);
        pbq->push(Task(x, y, myAdd));
    }
}

int main()
{
    // 种下随机数种子
    srand((unsigned int)time(nullptr) ^ getpid());

    pthread_t c[2], p[2];
    BlockQueue<Task> *pbq = new BlockQueue<Task>();
    assert(pbq);

    // 创建生产者和消费者线程
    int n = pthread_create(c, nullptr, consume, (void*)pbq);
    assert(n == 0);
    n = pthread_create(c + 1, nullptr, consume, (void*)pbq);
    assert(n == 0);
    n = pthread_create(p, nullptr, product, (void*)pbq);
    assert(n == 0);
    n = pthread_create(p + 1, nullptr, product, (void*)pbq);
    assert(n == 0);

    // 主线程阻塞等待子线程退出
    n = pthread_join(c[0], nullptr);
    assert(n == 0);
    n = pthread_join(c[1], nullptr);
    assert(n == 0);
    n = pthread_join(p[0], nullptr);
    assert(n == 0);
    n = pthread_join(p[0], nullptr);
    assert(n == 0);

    return 0;
}